'use strict';

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var testEmptyArray = function testEmptyArray(arr) {
    return arr == undefined ? [] : arr;
};

String.prototype.contains = function (str) {
    return this.indexOf(str) != -1;
};

String.prototype.escapeText = function () {
    return this.replace(/"/g, '\\"').replace(/\n/g, '\\\\n');
};

String.prototype.unescapeText = function () {
    return this.unescapeEnter().unescapeQuota();
};

String.prototype.escapeQuota = function () {
    return this.replace(/"/g, '\\"');
};

String.prototype.unescapeQuota = function () {
    return this.replace(/\\"/g, '"');
};

String.prototype.escapeEnter = function () {
    return this.replace(/\n/g, '\\\\n');
};

String.prototype.unescapeEnter = function () {
    return this.replace(/\\\\n/g, '\n');
};

function getRequest() {
    var url = location.search; //获取url中"?"符后的字串
    var theRequest = {};
    if (url.indexOf("?") != -1) {
        var str = url.substr(1);
        var strs = str.split("&");
        for (var i = 0; i < strs.length; i++) {
            theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
        }
    }
    return theRequest;
}

function getConfigure(ftype, callback) {
    if (ftype == null) {
        return;
    }

    var session = neo4jService.getSession();
    var resultPromise = session.run('MATCH (n:Configure) WHERE n.ftype="' + ftype + '" RETURN n');
    resultPromise.then(function (result) {
        session.close();
        var confs = result.records.map(function (record) {
            return record.get(0);
        });
        var rs = [];
        if (confs.length > 0) {
            var conf = confs[0];
            var data = conf['properties']['data'];
            rs = JSON.parse(data);
            // rs = data.map(x=>x.name);
        }
        callback(rs);
    });
}

var cache = {};
//异步缓存函数
function getCache(name, callback, supplier) {
    var timeout = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5000;

    var now = new Date().getTime();
    if (cache[name] && now - cache[name].lastTimestamp <= timeout) {
        callback(cache[name].value);
    } else {
        supplier(callback, cache, name);
    }
}
//同步的缓存
function getCacheSync(name, supplier) {
    var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 5000;

    var now = new Date().getTime();
    if (cache[name] && now - cache[name].lastTimestamp <= timeout) {
        return cache[name].value;
    } else {
        var val = supplier();
        cache[name] = {
            lastTimestamp: now,
            value: val
        };
        return val;
    }
}

window.basePort = localStorage.getItem("serverPort");
window.basePort = window.basePort || 8082;

(function (self) {
    var support = {
        searchParams: 'URLSearchParams' in self,
        iterable: 'Symbol' in self && 'iterator' in Symbol,
        blob: 'FileReader' in self && 'Blob' in self && function () {
            try {
                new Blob();
                return true;
            } catch (e) {
                return false;
            }
        }(),
        formData: 'FormData' in self,
        arrayBuffer: 'ArrayBuffer' in self
    };

    function isDataView(obj) {
        return obj && DataView.prototype.isPrototypeOf(obj);
    }

    if (support.arrayBuffer) {
        var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];

        var isArrayBufferView = ArrayBuffer.isView || function (obj) {
            return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
        };
    }

    var Headers = function () {
        function Headers(headers) {
            var _this = this;

            _classCallCheck(this, Headers);

            this.map = {};

            if (headers instanceof Headers) {
                headers.forEach(function (value, name) {
                    _this.append(name, value);
                }, this);
            } else if (Array.isArray(headers)) {
                headers.forEach(function (header) {
                    _this.append(header[0], header[1]);
                }, this);
            } else if (headers) {
                Object.getOwnPropertyNames(headers).forEach(function (name) {
                    _this.append(name, headers[name]);
                }, this);
            }
        }

        _createClass(Headers, [{
            key: 'append',
            value: function append(name, value) {
                name = Headers.normalizeName(name);
                value = Headers.normalizeValue(value);
                var oldValue = this.map[name];
                this.map[name] = oldValue ? oldValue + ', ' + value : value;
            }
        }, {
            key: 'get',
            value: function get(name) {
                name = Headers.normalizeName(name);
                return this.has(name) ? this.map[name] : null;
            }
        }, {
            key: 'has',
            value: function has(name) {
                return this.map.hasOwnProperty(Headers.normalizeName(name));
            }
        }, {
            key: 'set',
            value: function set(name, value) {
                this.map[Headers.normalizeName(name)] = Headers.normalizeValue(value);
            }
        }, {
            key: 'forEach',
            value: function forEach(callback, thisArg) {
                for (var name in this.map) {
                    if (this.map.hasOwnProperty(name)) {
                        callback.call(thisArg, this.map[name], name, this);
                    }
                }
            }
        }, {
            key: 'keys',
            value: function keys() {
                var items = [];
                this.forEach(function (value, name) {
                    items.push(name);
                });
                return Headers.iteratorFor(items);
            }
        }, {
            key: 'values',
            value: function values() {
                var items = [];
                this.forEach(function (value) {
                    items.push(value);
                });
                return Headers.iteratorFor(items);
            }
        }, {
            key: 'entries',
            value: function entries() {
                var items = [];
                this.forEach(function (value, name) {
                    items.push([name, value]);
                });
                return Headers.iteratorFor(items);
            }
        }], [{
            key: 'normalizeName',
            value: function normalizeName(name) {
                if (typeof name !== 'string') {
                    name = String(name);
                }
                if (/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(name)) {
                    throw new TypeError('Invalid character in header field name');
                }
                return name.toLowerCase();
            }
        }, {
            key: 'normalizeValue',
            value: function normalizeValue(value) {
                if (typeof value !== 'string') {
                    value = String(value);
                }
                return value;
            }

            // Build a destructive iterator for the value list

        }, {
            key: 'iteratorFor',
            value: function iteratorFor(items) {
                var iterator = {
                    next: function next() {
                        var value = items.shift();
                        return { done: value === undefined, value: value };
                    }
                };

                if (support.iterable) {
                    iterator[Symbol.iterator] = function () {
                        return iterator;
                    };
                }

                return iterator;
            }
        }]);

        return Headers;
    }();

    Headers.prototype['delete'] = function (name) {
        delete this.map[Headers.normalizeName(name)];
    };

    if (support.iterable) {
        Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
    }

    function consumed(body) {
        if (body.bodyUsed) {
            return Promise.reject(new TypeError('Already read'));
        }
        body.bodyUsed = true;
    }

    function fileReaderReady(reader) {
        return new Promise(function (resolve, reject) {
            reader.onload = function () {
                resolve(reader.result);
            };
            reader.onerror = function () {
                reject(reader.error);
            };
        });
    }

    function readBlobAsArrayBuffer(blob) {
        var reader = new FileReader();
        var promise = fileReaderReady(reader);
        reader.readAsArrayBuffer(blob);
        return promise;
    }

    function readBlobAsText(blob) {
        var reader = new FileReader();
        var promise = fileReaderReady(reader);
        reader.readAsText(blob);
        return promise;
    }

    function readArrayBufferAsText(buf) {
        var view = new Uint8Array(buf);
        var chars = new Array(view.length);

        for (var i = 0; i < view.length; i++) {
            chars[i] = String.fromCharCode(view[i]);
        }
        return chars.join('');
    }

    function bufferClone(buf) {
        if (buf.slice) {
            return buf.slice(0);
        } else {
            var view = new Uint8Array(buf.byteLength);
            view.set(new Uint8Array(buf));
            return view.buffer;
        }
    }

    var Body = function () {
        function Body() {
            _classCallCheck(this, Body);

            this.bodyUsed = false;
        }

        _createClass(Body, [{
            key: '_initBody',
            value: function _initBody(body) {
                this._bodyInit = body;
                if (!body) {
                    this._bodyText = '';
                } else if (typeof body === 'string') {
                    this._bodyText = body;
                } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
                    this._bodyBlob = body;
                } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
                    this._bodyFormData = body;
                } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
                    this._bodyText = body.toString();
                } else if (support.arrayBuffer && support.blob && isDataView(body)) {
                    this._bodyArrayBuffer = bufferClone(body.buffer);
                    // IE 10-11 can't handle a DataView body.
                    this._bodyInit = new Blob([this._bodyArrayBuffer]);
                } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
                    this._bodyArrayBuffer = bufferClone(body);
                } else {
                    this._bodyText = body = Object.prototype.toString.call(body);
                }

                if (!this.headers.get('content-type')) {
                    if (typeof body === 'string') {
                        this.headers.set('content-type', 'text/plain;charset=UTF-8');
                    } else if (this._bodyBlob && this._bodyBlob.type) {
                        this.headers.set('content-type', this._bodyBlob.type);
                    } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
                        this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
                    }
                }
            }
        }, {
            key: 'text',
            value: function text() {
                var rejected = consumed(this);
                if (rejected) {
                    return rejected;
                }

                if (this._bodyBlob) {
                    return readBlobAsText(this._bodyBlob);
                } else if (this._bodyArrayBuffer) {
                    return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
                } else if (this._bodyFormData) {
                    throw new Error('could not read FormData body as text');
                } else {
                    return Promise.resolve(this._bodyText);
                }
            }
        }, {
            key: 'json',
            value: function json() {
                return this.text().then(JSON.parse);
            }
        }]);

        return Body;
    }();

    if (support.blob) {
        Body.prototype.blob = function () {
            var rejected = consumed(this);
            if (rejected) {
                return rejected;
            }

            if (this._bodyBlob) {
                return Promise.resolve(this._bodyBlob);
            } else if (this._bodyArrayBuffer) {
                return Promise.resolve(new Blob([this._bodyArrayBuffer]));
            } else if (this._bodyFormData) {
                throw new Error('could not read FormData body as blob');
            } else {
                return Promise.resolve(new Blob([this._bodyText]));
            }
        };

        Body.prototype.arrayBuffer = function () {
            if (this._bodyArrayBuffer) {
                return consumed(this) || Promise.resolve(this._bodyArrayBuffer);
            } else {
                return this.blob().then(readBlobAsArrayBuffer);
            }
        };
    }

    if (support.formData) {
        Body.prototype.formData = function () {
            return this.text().then(decode);
        };
    }

    // HTTP methods whose capitalization should be normalized
    var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];

    function normalizeMethod(method) {
        var upcased = method.toUpperCase();
        return methods.indexOf(upcased) > -1 ? upcased : method;
    }

    var Request = function (_Body) {
        _inherits(Request, _Body);

        function Request(input, options) {
            _classCallCheck(this, Request);

            var _this2 = _possibleConstructorReturn(this, (Request.__proto__ || Object.getPrototypeOf(Request)).call(this));

            options = options || {};
            var body = options.body;

            if (input instanceof Request) {
                if (input.bodyUsed) {
                    throw new TypeError('Already read');
                }
                _this2.url = input.url;
                _this2.credentials = input.credentials;
                if (!options.headers) {
                    _this2.headers = new Headers(input.headers);
                }
                _this2.method = input.method;
                _this2.mode = input.mode;
                _this2.signal = input.signal;
                if (!body && input._bodyInit != null) {
                    body = input._bodyInit;
                    input.bodyUsed = true;
                }
            } else {
                _this2.url = String(input);
            }

            _this2.credentials = options.credentials || _this2.credentials || 'same-origin';
            if (options.headers || !_this2.headers) {
                _this2.headers = new Headers(options.headers);
            }
            _this2.method = normalizeMethod(options.method || _this2.method || 'GET');
            _this2.mode = options.mode || _this2.mode || null;
            _this2.signal = options.signal || _this2.signal;
            _this2.referrer = null;

            if ((_this2.method === 'GET' || _this2.method === 'HEAD') && body) {
                throw new TypeError('Body not allowed for GET or HEAD requests');
            }
            _this2._initBody(body);
            return _this2;
        }

        _createClass(Request, [{
            key: 'clone',
            value: function clone() {
                return new Request(this, { body: this._bodyInit });
            }
        }]);

        return Request;
    }(Body);

    function decode(body) {
        var form = new FormData();
        body.trim().split('&').forEach(function (bytes) {
            if (bytes) {
                var split = bytes.split('=');
                var name = split.shift().replace(/\+/g, ' ');
                var value = split.join('=').replace(/\+/g, ' ');
                form.append(decodeURIComponent(name), decodeURIComponent(value));
            }
        });
        return form;
    }

    function parseHeaders(rawHeaders) {
        var headers = new Headers();
        // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
        // https://tools.ietf.org/html/rfc7230#section-3.2
        var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
        preProcessedHeaders.split(/\r?\n/).forEach(function (line) {
            var parts = line.split(':');
            var key = parts.shift().trim();
            if (key) {
                var value = parts.join(':').trim();
                headers.append(key, value);
            }
        });
        return headers;
    }

    // Body.call(Request.prototype);

    var Response = function (_Body2) {
        _inherits(Response, _Body2);

        function Response(bodyInit, options) {
            _classCallCheck(this, Response);

            var _this3 = _possibleConstructorReturn(this, (Response.__proto__ || Object.getPrototypeOf(Response)).call(this));

            if (!options) {
                options = {};
            }

            _this3.type = 'default';
            _this3.status = options.status === undefined ? 200 : options.status;
            _this3.ok = _this3.status >= 200 && _this3.status < 300;
            _this3.statusText = 'statusText' in options ? options.statusText : 'OK';
            _this3.headers = new Headers(options.headers);
            _this3.url = options.url || '';
            _this3._initBody(bodyInit);
            return _this3;
        }

        _createClass(Response, [{
            key: 'clone',
            value: function clone() {
                return new Response(this._bodyInit, {
                    status: this.status,
                    statusText: this.statusText,
                    headers: new Headers(this.headers),
                    url: this.url
                });
            }
        }, {
            key: 'error',
            value: function error() {
                var response = new Response(null, { status: 0, statusText: '' });
                response.type = 'error';
                return response;
            }
        }, {
            key: 'redirect',
            value: function redirect(url, status) {
                if (Response.redirectStatuses.indexOf(status) === -1) {
                    throw new RangeError('Invalid status code');
                }
                return new Response(null, { status: status, headers: { location: url } });
            }
        }]);

        return Response;
    }(Body);

    Response.redirectStatuses = [301, 302, 303, 307, 308];

    // Body.call(Response.prototype)


    var DOMException = self.DOMException;
    try {
        new DOMException();
    } catch (err) {
        DOMException = function DOMException(message, name) {
            _classCallCheck(this, DOMException);

            this.message = message;
            this.name = name;
            var error = Error(message);
            this.stack = error.stack;
        };
        DOMException.prototype = Object.create(Error.prototype);
        DOMException.prototype.constructor = DOMException;
    }

    function fetch(input, init) {
        return new Promise(function (resolve, reject) {
            var request = new Request(input, init);

            if (request.signal && request.signal.aborted) {
                return reject(new DOMException('Aborted', 'AbortError'));
            }

            var xhr = new XMLHttpRequest();

            function abortXhr() {
                xhr.abort();
            }

            xhr.onload = function () {
                var options = {
                    status: xhr.status,
                    statusText: xhr.statusText,
                    headers: parseHeaders(xhr.getAllResponseHeaders() || '')
                };
                options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
                var body = 'response' in xhr ? xhr.response : xhr.responseText;
                resolve(new Response(body, options));
            };

            xhr.onerror = function () {
                reject(new TypeError('Network request failed'));
            };

            xhr.ontimeout = function () {
                reject(new TypeError('Network request failed'));
            };

            xhr.onabort = function () {
                reject(new DOMException('Aborted', 'AbortError'));
            };

            xhr.open(request.method, request.url, true);

            if (request.credentials === 'include') {
                xhr.withCredentials = true;
            } else if (request.credentials === 'omit') {
                xhr.withCredentials = false;
            }

            if ('responseType' in xhr && support.blob) {
                xhr.responseType = 'blob';
            }

            request.headers.forEach(function (value, name) {
                xhr.setRequestHeader(name, value);
            });

            if (request.signal) {
                request.signal.addEventListener('abort', abortXhr);

                xhr.onreadystatechange = function () {
                    // DONE (success or failure)
                    if (xhr.readyState === 4) {
                        request.signal.removeEventListener('abort', abortXhr);
                    }
                };
            }

            xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
        });
    }

    fetch.polyfill = true;

    if (!self.fetch) {
        self.fetch = fetch;
        self.Headers = Headers;
        self.Request = Request;
        self.Response = Response;
    }
})(window);
if (!neo4j_config) {
    var neo4j_config = {
        useNeo4j: true,
        url: "bolt://" + window.location.hostname,
        user: "neo4j",
        password: "123456"
    };
}

var Neo4jService = function () {
    function Neo4jService() {
        _classCallCheck(this, Neo4jService);

        this.rebuild();
    }

    _createClass(Neo4jService, [{
        key: 'getSession',
        value: function getSession() {
            if (neo4j_config.useNeo4j) {
                return this.driver.session();
            }
            return this.remoteSession;
        }
    }, {
        key: 'closeConnection',
        value: function closeConnection() {
            if (neo4j_config.useNeo4j) {
                this.driver.close();
            }
        }
    }, {
        key: 'rebuild',
        value: function rebuild() {
            if (neo4j_config.useNeo4j) {
                this.driver = neo4j.v1.driver(neo4j_config.url, neo4j.v1.auth.basic(neo4j_config.user, neo4j_config.password));
            } else {
                this.remoteSession = new RemoteNeo4jServiceSession(neo4j_config);
            }
        }
    }]);

    return Neo4jService;
}();

var MyRecord = function () {
    function MyRecord(record) {
        _classCallCheck(this, MyRecord);

        this.keys = Object.keys(record);
        this.valueMap = record;
    }

    _createClass(MyRecord, [{
        key: 'get',
        value: function get(indexOrName) {
            if (indexOrName in this.valueMap) {
                return this.valueMap[indexOrName];
            }
            if (typeof indexOrName === 'number' && indexOrName % 1 === 0 && indexOrName >= 0 && indexOrName < this.keys.length) {
                return this.valueMap[this.keys[indexOrName]];
            }
            return null;
        }
    }]);

    return MyRecord;
}();

var RemoteNeo4jServiceSession = function () {
    function RemoteNeo4jServiceSession(conf) {
        _classCallCheck(this, RemoteNeo4jServiceSession);

        this.config = Object.assign({}, RemoteNeo4jServiceSession.default, conf);
    }

    _createClass(RemoteNeo4jServiceSession, [{
        key: 'run',
        value: function run(cypher) {
            var formData = new FormData();
            formData.append('cypher', cypher);
            return fetch(this.config.base_url, {
                method: "POST",
                body: formData
                // headers:{
                //     "Content-Type": "application/x-www-form-urlencoded"
                // }
            }).then(function (response) {
                return response.json();
            }).then(function (records) {
                return {
                    records: records.map(function (r) {
                        return new MyRecord(r);
                    })
                };
            });
        }
    }, {
        key: 'close',
        value: function close() {}
    }]);

    return RemoteNeo4jServiceSession;
}();

RemoteNeo4jServiceSession.default = {
    base_url: 'http://127.0.0.1:8080/cypher'
};

var neo4jService = new Neo4jService();

var Edge = function () {
    function Edge(g, from, to) {
        var $state = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'new';

        _classCallCheck(this, Edge);

        Edge.idGenerator++;
        this.graph = g;
        this.from = from;
        this.to = to;
        this.$state = $state;
        this.$removed = false;
        this.id = Edge.idGenerator;
    }

    _createClass(Edge, [{
        key: 'linkType',
        value: function linkType() {
            var edgeType = "linkTo";
            switch (this.graph.getNode(this.to).$type) {
                case 'Component':
                case 'ComponentGroup':
                    edgeType = this.graph.getNode(this.from).$type == 'ComponentGroup' ? 'contains' : 'of';
                    break;
                case 'Feature':
                case 'FeatureGroup':
                    edgeType = this.graph.getNode(this.from).$type == 'FeatureGroup' ? 'contains' : 'hasFeatures';
                    break;
                case 'Reason':
                case 'ReasonGroup':
                    edgeType = this.graph.getNode(this.from).$type == 'ReasonGroup' ? 'contains' : 'hasReasons';
                    break;
            }
            return edgeType;
        }
    }, {
        key: 'persist',
        value: function persist() {
            if (this.$state == 'new') {
                if (this.$removed) return;
                var session = neo4jService.getSession();
                var resultPromise = session.run('start f=node(' + this.from + '),t=node(' + this.to + ') create (f)-[r:' + this.linkType() + ']->(t) return r ');
                resultPromise.then(function (result) {
                    session.close();
                });
            } else //if(this.$state=='dirty')
                {
                    if (this.$removed) {
                        var _session = neo4jService.getSession();
                        var _resultPromise = _session.run('start f=node(' + this.from + '),t=node(' + this.to + ') match (f)-[r]->(t) delete r ');
                        _resultPromise.then(function (result) {
                            _session.close();
                        });
                    } else {}
                    //do nothing

                    // let sets = '';
                    // for(let key of Object.keys(node)){
                    //     if(!/^\$\S+/g.test(key) && key!='id'){
                    //         sets=`${sets} set n.${key}="${node[key]}" `
                    //     }
                    // }

                }
        }
    }]);

    return Edge;
}();

Edge.idGenerator = 0;
var node_icon = {
    'Fault': ["glyphicon", "glyphicon-alert"],
    'Feature': ["glyphicon", "glyphicon-star"],
    'Reason': ["glyphicon", "glyphicon-star-empty"],
    'Component': ["glyphicon", "glyphicon-cog"],
    'FeatureGroup': ["glyphicon", "glyphicon-folder-open"],
    'ReasonGroup': ["glyphicon", "glyphicon-folder-open"],
    'ComponentGroup': ["glyphicon", "glyphicon-folder-open"]
};

var Graph = function () {
    function Graph() {
        _classCallCheck(this, Graph);

        this.nodes = new Map();
        this.edges = [];
        this.matchedNodes = [];
    }

    _createClass(Graph, [{
        key: 'addNode',
        value: function addNode(node) {
            this.nodes.set(node.id, node);
        }
    }, {
        key: 'getNode',
        value: function getNode(id) {
            return this.nodes.get('' + id);
        }
    }, {
        key: 'getNodeFromList',
        value: function getNodeFromList(id, list) {
            return [].concat(_toConsumableArray(list)).find(function (n) {
                return n.id == '' + id;
            });
        }
    }, {
        key: 'addLink',
        value: function addLink(from, to) {
            var $state = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'new';

            var edges = this.edges.filter(function (edge) {
                return '' + edge.from === '' + from && '' + edge.to === '' + to;
            });
            if (edges.length > 0) {
                edges.forEach(function (edge) {
                    return edge.$removed = true;
                });
                edges[0].$removed = false;
            } else if (this.getNode('' + from) == null || this.getNode('' + to) == null) {
                var newEdge = new Edge(this, from, to, $state);
                newEdge.$removed = true;
                this.edges.push(newEdge);
            } else this.edges.push(new Edge(this, from, to, $state));
        }
    }, {
        key: 'getLink',
        value: function getLink(id) {
            for (var i = 0; i < this.edges.length; i++) {
                var eg = this.edges[i];
                if ('' + eg.id == '' + id) return eg;
            }
        }
    }, {
        key: 'getLinkIndex',
        value: function getLinkIndex(id) {
            for (var i = 0; i < this.edges.length; i++) {
                var eg = this.edges[i];
                if ('' + eg.id == '' + id) return i;
            }
            return -1;
        }
    }, {
        key: 'resetLink',
        value: function resetLink(edgeId, toNode, callback) {
            for (var i = 0; i < this.edges.length; i++) {
                var eg = this.edges[i];
                if ('' + eg.id == '' + edgeId) {
                    var neg = new Edge(this, eg.from, toNode.id);
                    eg.$removed = true;
                    this.addNode(toNode);
                    this.edges.push(neg);
                    break;
                }
            }
            if (callback != null && callback instanceof Function) {
                callback(this);
            }
        }
    }, {
        key: 'toJsonTree',
        value: function toJsonTree() {
            //TODO 转为 bootstrap 所需的树状结构
            var that = this;
            function toTree(nodeId, fromEdge) {
                var sub_edges = [].concat(_toConsumableArray(that.edges)).filter(function (edge) {
                    return !edge.$removed && edge.from == nodeId;
                });
                var node = that.getNode(nodeId);
                if (sub_edges.length > 0) {
                    return {
                        text: node.getText(),
                        referId: nodeId,
                        referEdge: fromEdge,
                        icon: node_icon[node.$type],
                        selectable: true,
                        isMatched: node.isMatched || that.matchedNodes.some(function (nid) {
                            return nid = node.id;
                        }),
                        children: sub_edges.map(function (edge) {
                            return toTree(edge.to, edge.id);
                        })
                    };
                } else {
                    return {
                        text: node.getText(),
                        referId: nodeId,
                        referEdge: fromEdge,
                        icon: node_icon[node.$type],
                        selectable: true,
                        isMatched: node.isMatched || that.matchedNodes.some(function (nid) {
                            return nid = node.id;
                        }),
                        children: []
                    };
                }
            }

            var nodesList = [].concat(_toConsumableArray(this.nodes.values()));
            var root = nodesList.filter(function (node) {
                return node.$type == 'Fault';
            })[0];
            return toTree(root.id, null);
        }
    }, {
        key: 'toJson',
        value: function toJson() {
            var that = this;
            function exposeJson(node) {
                var json = node.toJson();
                var sub_edges = [].concat(_toConsumableArray(that.edges)).filter(function (edge) {
                    return !edge.$removed && edge.from == node.id;
                });
                if (sub_edges.length > 0) {
                    json["children"] = sub_edges.map(function (edge) {
                        return that.getNode(edge.to);
                    }).map(function (nd) {
                        return exposeJson(nd);
                    });
                }
                return json;
            }

            var fault = this.getRoot();
            return exposeJson(fault);
        }
    }, {
        key: 'getRoot',
        value: function getRoot() {
            var nodesList = [].concat(_toConsumableArray(this.nodes.values()));
            var root = nodesList.filter(function (node) {
                return node.$type == 'Fault';
            })[0];
            return root;
        }
    }, {
        key: 'getReasons',
        value: function getReasons() {
            var _this4 = this;

            return _(this.edges).chain().filter(function (edge) {
                return !edge.$removed;
            }).map(function (edge) {
                return edge.to;
            }).uniq().map(function (id) {
                return _this4.getNode(id);
            }).filter(function (node) {
                return node.$type == 'Reason';
            }).value().sort(MyNode.compare);

            // let nodesList = [... this.nodes.values()].filter(node=>node.$type=='Reason').sort(MyNode.compare);
            // return nodesList;
        }
    }, {
        key: 'getFeatures',
        value: function getFeatures() {
            var _this5 = this;

            return _(this.edges).chain().filter(function (edge) {
                return !edge.$removed;
            }).map(function (edge) {
                return edge.to;
            }).uniq().map(function (id) {
                return _this5.getNode(id);
            }).filter(function (node) {
                return node.$type == 'Feature';
            }).value().sort(MyNode.compare);
            // let nodesList = [... this.nodes.values()].filter(node=>node.$type=='Feature').sort(MyNode.compare);
            // return nodesList;
        }
    }, {
        key: 'getFeatureSize',
        value: function getFeatureSize() {
            return this.getFeatures().length;
        }
    }, {
        key: 'getReasonSize',
        value: function getReasonSize() {
            return this.getReasons().length;
        }
    }, {
        key: 'markSubGraph',
        value: function markSubGraph() {
            var that = this;
            var session = neo4jService.getSession();
            function mark(node) {
                if (node.$type == 'Feature' || node.$type == 'FeatureGroup' && node.combineType != 'or') {
                    return new Promise(function (resolve, reject) {
                        node.$is_sub_graph = true;
                        resolve();
                    });
                } else if (node.$type == 'Fault' || node.$type == 'FeatureGroup' && node.combineType == 'or') {
                    return MyNode.nextHop(session, node.id).then(function (nextHop) {
                        return Promise.all(nextHop.map(function (nd) {
                            var t_nd = that.getNode(nd.id);
                            return mark(t_nd);
                        }));
                    });
                }
            }
            return mark(that.getRoot());
        }
    }, {
        key: 'markSubGraph2',
        value: function markSubGraph2() {
            var that = this;
            var session = neo4jService.getSession();
            function mark2(node, reasonId) {
                if (node.$type == 'Feature' || node.$type == 'FeatureGroup' && node.combineType != 'or') {
                    return new Promise(function (resolve, reject) {
                        node.$is_sub_graph2 = true;
                        node.$reasons.add(reasonId);
                        resolve();
                    });
                } else if (node.$type == 'Fault' || node.$type == 'ReasonGroup' || node.$type == 'Reason' || node.$type == 'FeatureGroup' && node.combineType == 'or') {
                    return MyNode.nextHop(session, node.id).then(function (nextHop) {
                        return Promise.all(nextHop.map(function (nd) {
                            var t_nd = that.getNode(nd.id);
                            if (node.$type == 'Fault' || node.$type == 'ReasonGroup') {
                                return mark2(t_nd, null);
                            } else if (node.$type == 'Reason') {
                                return mark2(t_nd, node.id);
                            } else if (reasonId != null) {
                                return mark2(t_nd, reasonId);
                            }
                            return Promise.resolve(t_nd);
                        }));
                    });
                }
            }
            return mark2(that.getRoot(), null);
        }
    }, {
        key: 'removeFromDB',
        value: function removeFromDB(callback) {
            var root = this.getRoot();
            var fail = function fail(e) {
                console.error(e);
            };

            var session = neo4jService.getSession();

            session.run('match (n)-[*]->()-[r]->(m:Component) where id(n)=' + root.id + ' delete r ').then(function (r1) {
                return session.run('match (n)-[r]->() where id(n)=' + root.id + ' delete r delete n');
            }).then(function (r2) {
                return 'match (n) where n:Component or n:Configure with id(n) as x return x union match p=(n:Fault)-[*]->() with nodes(p) as pl unwind pl as xn with id(xn) as x return distinct x';
            }).then(function (r3) {
                var ids = r3.records.map(function (record) {
                    return record.get(0);
                });
                return session.run('with [' + ids.join(",") + '] as nids match (n)-[r]-() where not id(n) in nids delete r delete n').then(function () {
                    return ids;
                });
            }).then(function (ids) {
                return session.run('with [' + ids.join(",") + '] as nids match (n) where not id(n) in nids delete n');
            }).then(function () {
                session.close();
                callback && callback();
            }).catch(function (e) {
                if (fail != null && fail instanceof Function) {
                    fail(e);
                }
            });

            // Neo4jService.doExecute(session,`match (n)-[*]->()-[r]->(m:Component) where id(n)=${root.id} delete r `,(r1)=>{
            //     Neo4jService.doExecute(session,`match (n)-[r]->() where id(n)=${root.id} delete r delete n`,(r2)=>{
            //         Neo4jService.doExecute(session,`match (n) where n:Component or n:Configure with id(n) as x return x union match p=(n:Fault)-[*]->() with nodes(p) as pl unwind pl as xn with id(xn) as x return distinct x`,(r3)=>{
            //             const ids = r3.records.map((record) => record.get(0));
            //             Neo4jService.doExecute(session,`with [${ids.join(",")}] as nids match (n)-[r]-() where not id(n) in nids delete r delete n`,(r4)=>{
            //                 Neo4jService.doExecute(session,`with [${ids.join(",")}] as nids match (n) where not id(n) in nids delete n`,(r5)=>{
            //                     session.close();
            //                     callback && callback();
            //                 },fail);
            //             },fail);
            //         },fail);
            //     },fail);
            // },fail);
        }
    }, {
        key: 'persistClone',
        value: function persistClone(success, fail) {
            var nds = [].concat(_toConsumableArray(this.nodes.values()));

            nds = nds.filter(function (nd) {
                return nd.$type != 'Component' && nd.$state != 'new';
            }).map(function (node) {
                node.$state = 'new';
                return node;
            });

            this.edges = this.edges.filter(function (eg) {
                return eg.$state != 'new';
            }).map(function (eg) {
                eg.$state = 'new';
                return eg;
            });

            var rawEntities = nds.filter(function (nd) {
                return nd.$state != 'new';
            }).map(function (node) {
                return 'n' + node.id + '=node(' + node.id + ')';
            });
            var modifiedEntity = nds.filter(function (nd) {
                return nd.$state != 'new';
            }).map(function (node) {
                var str = '';
                var _iteratorNormalCompletion = true;
                var _didIteratorError = false;
                var _iteratorError = undefined;

                try {
                    for (var _iterator = Object.keys(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                        var key = _step.value;

                        if (!/^\$\S+/g.test(key) && key != 'id') {
                            var jsonStr = angular.toJson(node[key], false);
                            str = str + ' set n' + node.id + '.' + key + '=' + jsonStr + ' ';
                        }
                    }
                } catch (err) {
                    _didIteratorError = true;
                    _iteratorError = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion && _iterator.return) {
                            _iterator.return();
                        }
                    } finally {
                        if (_didIteratorError) {
                            throw _iteratorError;
                        }
                    }
                }

                return str;
            });

            var entities = nds.filter(function (nd) {
                return nd.$state == 'new';
            }).map(function (node) {
                return '(n' + node.id + node.toString() + ') ';
            });

            var rawEdges = this.edges.filter(function (eg) {
                return eg.$state != 'new' && eg.$removed;
            }).map(function (eg) {
                return '(n' + eg.from + ')-[r' + eg.id + ']->(n' + eg.to + ')';
            });
            var newEdges = this.edges.filter(function (eg) {
                return eg.$state == 'new' && !eg.$removed;
            }).map(function (eg) {
                return '(n' + eg.from + ')-[r' + eg.id + ':' + eg.linkType() + ']->(n' + eg.to + ')';
            });
            var deleteEdges = this.edges.filter(function (eg) {
                return eg.$state != 'new' && eg.$removed;
            }).map(function (eg) {
                return 'r' + eg.id;
            });

            var qstring = '';
            if (rawEntities.length > 0) qstring = qstring + ' start ' + rawEntities.join(',');
            if (rawEdges.length > 0) qstring = qstring + ' match ' + rawEdges.join(',');
            if (entities.length > 0) qstring = qstring + ' create ' + entities.join(',');
            if (newEdges.length > 0) qstring = qstring + ' create ' + newEdges.join(',');
            if (modifiedEntity.length > 0) qstring = qstring + ' ' + modifiedEntity.join(' ');
            if (deleteEdges.length > 0) qstring = qstring + ' delete ' + deleteEdges.join(',');

            var session = neo4jService.getSession();
            var resultPromise = session.run(qstring);
            resultPromise.catch(function (e) {
                if (fail != null && fail instanceof Function) {
                    fail(e);
                }
            }).then(function (result) {
                session.close();
                FaultNode.loadFaults();
                if (success != null && success instanceof Function) {
                    success(result);
                }
            });
        }
    }, {
        key: 'markFreedomNode',
        value: function markFreedomNode() {
            var that = this;
            function mark(node, parent_type /* or--1 , and--0 */) {
                if (node instanceof FeatureNode) {
                    if (parent_type == "or") {
                        node.$freedom = true;
                        node.$freelist = [node.id];
                    }
                } else {
                    var _iteratorNormalCompletion2 = true;
                    var _didIteratorError2 = false;
                    var _iteratorError2 = undefined;

                    try {
                        for (var _iterator2 = that.edges.filter(function (edge) {
                            return edge.from == node.id;
                        })[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                            var edge = _step2.value;

                            var subnode = that.getNode(edge.to);
                            edge.$freedom = true;
                            mark(subnode, node.combineType);
                        }
                    } catch (err) {
                        _didIteratorError2 = true;
                        _iteratorError2 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion2 && _iterator2.return) {
                                _iterator2.return();
                            }
                        } finally {
                            if (_didIteratorError2) {
                                throw _iteratorError2;
                            }
                        }
                    }

                    var list = [];
                    var _iteratorNormalCompletion3 = true;
                    var _didIteratorError3 = false;
                    var _iteratorError3 = undefined;

                    try {
                        for (var _iterator3 = that.edges.filter(function (edge) {
                            return edge.from == node.id;
                        })[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                            var _edge = _step3.value;

                            var subnode = that.getNode(_edge.to);
                            list.concat(subnode.$freelist || []);
                        }
                    } catch (err) {
                        _didIteratorError3 = true;
                        _iteratorError3 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion3 && _iterator3.return) {
                                _iterator3.return();
                            }
                        } finally {
                            if (_didIteratorError3) {
                                throw _iteratorError3;
                            }
                        }
                    }

                    node.$freelist = list;
                }
            }
            mark(this.getRoot(), 1);
        }
    }, {
        key: 'persist',
        value: function persist(success, fail) {
            this.getRoot()["updateTimestamp"] = new Date().getTime();
            var nds = [].concat(_toConsumableArray(this.nodes.values()));
            // nds.forEach(nd=>nd.persist());
            // this.edges.forEach(eg=>eg.persist());

            var rawEntities = nds.filter(function (nd) {
                return nd.$state != 'new';
            }).map(function (node) {
                return 'n' + node.id + '=node(' + node.id + ')';
            });
            var modifiedEntity = nds.filter(function (nd) {
                return nd.$state != 'new';
            }).map(function (node) {
                var str = '';
                var _iteratorNormalCompletion4 = true;
                var _didIteratorError4 = false;
                var _iteratorError4 = undefined;

                try {
                    for (var _iterator4 = Object.keys(node)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
                        var key = _step4.value;

                        if (key == "updateTimestamp") {
                            str = str + ' set n' + node.id + '.' + key + '=' + node[key] + ' ';
                        } else if (!/^\$\S+/g.test(key) && key != 'id' && key != 'isMatched' && key != 'unknown') {
                            if (key == 'matrix' && _.isObject(node[key]) && !_.isArray(node[key])) {
                                node[key]["length"] = (node[key][0] + 1) * (node[key][1] + 1) + 2;
                                node[key] = Array.from(node[key]);
                                node[key] = _(node[key]).chain().map(function (x) {
                                    return x instanceof Number ? x : parseFloat(x);
                                }).value();
                            }

                            var jsonStr = angular.toJson(node[key], false);
                            if (key == "frequency") {
                                jsonStr = angular.toJson(jsonStr);
                            }
                            str = str + ' set n' + node.id + '.' + key + '=' + jsonStr + ' ';
                        }
                    }
                } catch (err) {
                    _didIteratorError4 = true;
                    _iteratorError4 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion4 && _iterator4.return) {
                            _iterator4.return();
                        }
                    } finally {
                        if (_didIteratorError4) {
                            throw _iteratorError4;
                        }
                    }
                }

                return str;
            });

            var entities = nds.filter(function (nd) {
                return nd.$state == 'new' && !nd.$removed;
            }).map(function (node) {
                return '(n' + node.id + node.toString() + ') ';
            });

            var rawEdges = this.edges.filter(function (eg) {
                return eg.$state != 'new' && eg.$removed;
            }).map(function (eg) {
                return '(n' + eg.from + ')-[r' + eg.id + ']->(n' + eg.to + ')';
            });
            var newEdges = this.edges.filter(function (eg) {
                return eg.$state == 'new' && !eg.$removed;
            }).map(function (eg) {
                return '(n' + eg.from + ')-[r' + eg.id + ':' + eg.linkType() + ']->(n' + eg.to + ')';
            });
            var deleteEdges = this.edges.filter(function (eg) {
                return eg.$state != 'new' && eg.$removed;
            }).map(function (eg) {
                return 'r' + eg.id;
            });

            var qstring = '';
            if (rawEntities.length > 0) qstring = qstring + ' start ' + rawEntities.join(',');
            if (rawEdges.length > 0) qstring = qstring + ' match ' + rawEdges.join(',');
            if (entities.length > 0) qstring = qstring + ' create ' + entities.join(',');
            if (newEdges.length > 0) qstring = qstring + ' create ' + newEdges.join(',');
            if (modifiedEntity.length > 0) qstring = qstring + ' ' + modifiedEntity.join(' ');
            if (deleteEdges.length > 0) qstring = qstring + ' delete ' + deleteEdges.join(',');

            var session = neo4jService.getSession();
            var resultPromise = session.run(qstring);
            resultPromise.catch(function (e) {
                if (fail != null && fail instanceof Function) {
                    fail(e);
                }
            }).then(function (result) {
                session.close();
                FaultNode.loadFaults();
                if (success != null && success instanceof Function) {
                    success(result);
                }
            });
        }
    }], [{
        key: 'merge',
        value: function merge() {
            var g = new Graph();

            for (var _len = arguments.length, gs = Array(_len), _key = 0; _key < _len; _key++) {
                gs[_key] = arguments[_key];
            }

            g.nodes = new Map(gs.map(function (gg) {
                return gg.nodes.keys();
            }).reduce(function (x, y) {
                return x.concat(y);
            }, []), gs.map(function (gg) {
                return gg.nodes.values();
            }).reduce(function (x, y) {
                return x.concat(y);
            }, []));
            g.edges = gs.map(function (gg) {
                return gg.edges;
            }).reduce(function (x, y) {
                return x.concat(y);
            }, []);
        }
    }, {
        key: 'loadGraph',
        value: function loadGraph(startId, callback) {
            return Graph.loadGraphPromise(startId).then(callback);
        }
    }, {
        key: 'loadGraphPromise',
        value: function loadGraphPromise(startId) {
            return new Promise(function (resolve, reject) {
                resolve({
                    g: new Graph(),
                    session: neo4jService.getSession()
                });
            }).then(function (context) {
                return new Promise(function (resolve, reject) {
                    var g = context.g,
                        session = context.session;

                    session.run('start n=node(' + startId + ') MATCH (n)-[*]->(a) RETURN a UNION start a=node(' + startId + ') RETURN a').then(function (result) {
                        result.records.map(function (record) {
                            return record.get(0);
                        }).map(function (node) {
                            return MyNode.fromNeo4jNode(node);
                        }).forEach(function (node) {
                            return g.nodes.set(node.id, node);
                        });
                        resolve(context);
                    }, function (fail) {
                        resolve(context);
                    });
                });
            }).then(function (context) {
                return new Promise(function (resolve, reject) {
                    var g = context.g,
                        session = context.session;

                    session.run('start n=node(' + startId + ') match p=(n)-[*]->(a) return relationships(p)[-1]').then(function (result) {
                        result.records.map(function (record) {
                            return record.get(0);
                        }).forEach(function (edge) {
                            return g.addLink(edge["start"].toString(), edge["end"].toString(), 'raw');
                        });
                        resolve(context);
                    });
                });
            }).then(function (context) {
                var g = context.g,
                    session = context.session;

                session.close();
                return g;
            });
        }
    }, {
        key: 'loadAllGraph',
        value: function loadAllGraph() {
            return new Promise(function (resolve, reject) {
                resolve({
                    g: new Graph(),
                    session: neo4jService.getSession()
                });
            }).then(function (context) {
                return new Promise(function (resolve, reject) {
                    var g = context.g,
                        session = context.session;

                    session.run('MATCH (n) where not "Configure" in labels(n)  RETURN n').then(function (result) {
                        result.records.map(function (record) {
                            return record.get(0);
                        }).map(function (node) {
                            return MyNode.fromNeo4jNode(node);
                        }).forEach(function (node) {
                            if (!node || !node.id) {
                                console.info(node);
                            } else g.nodes.set(node.id, node);
                        });
                        resolve(context);
                    }, function (fail) {
                        resolve(context);
                    });
                });
            }).then(function (context) {
                return new Promise(function (resolve, reject) {
                    var g = context.g,
                        session = context.session;

                    session.run('match ()-[r]->() return r').then(function (result) {
                        result.records.map(function (record) {
                            return record.get(0);
                        }).forEach(function (edge) {
                            return g.addLink(edge["start"].toString(), edge["end"].toString(), 'raw');
                        });
                        resolve(context);
                    });
                });
            }).then(function (context) {
                var g = context.g,
                    session = context.session;

                session.close();
                return g;
            });
        }
    }]);

    return Graph;
}();

var MyNode = function () {
    function MyNode(type) {
        var $state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'new';

        _classCallCheck(this, MyNode);

        MyNode.idGenerator++;
        this.$type = type;
        this.$state = $state;
        this.id = 'n' + MyNode.idGenerator;
        this.isMatched = false;
        this.unknown = false;

        for (var _len2 = arguments.length, obj = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
            obj[_key2 - 2] = arguments[_key2];
        }

        var _iteratorNormalCompletion5 = true;
        var _didIteratorError5 = false;
        var _iteratorError5 = undefined;

        try {
            for (var _iterator5 = obj[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
                var o = _step5.value;
                var _iteratorNormalCompletion6 = true;
                var _didIteratorError6 = false;
                var _iteratorError6 = undefined;

                try {

                    for (var _iterator6 = Object.keys(o)[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
                        var key = _step6.value;

                        var v = o[key];
                        if (typeof v == 'string') {
                            v = v.unescapeText();
                            try {
                                if (v.startsWith('[') || v.startsWith('{') || v.startsWith('"')) {
                                    v = JSON.parse(v.replace(/\n/g, '\\n'));
                                }
                            } catch (e) {
                                console.error(e);
                                console.error(v);
                            }
                        }
                        this[key] = v;
                    }
                } catch (err) {
                    _didIteratorError6 = true;
                    _iteratorError6 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion6 && _iterator6.return) {
                            _iterator6.return();
                        }
                    } finally {
                        if (_didIteratorError6) {
                            throw _iteratorError6;
                        }
                    }
                }
            }
            // jQuery.extend(true,this,...obj);
        } catch (err) {
            _didIteratorError5 = true;
            _iteratorError5 = err;
        } finally {
            try {
                if (!_iteratorNormalCompletion5 && _iterator5.return) {
                    _iterator5.return();
                }
            } finally {
                if (_didIteratorError5) {
                    throw _iteratorError5;
                }
            }
        }
    }

    _createClass(MyNode, [{
        key: 'getLinks',
        value: function getLinks(g) {
            var _this6 = this;

            return [].concat(_toConsumableArray(new Set(g.edges))).filter(function (edge) {
                return !edge.$removed && edge.from === _this6.id;
            }, this);
        }
    }, {
        key: 'toString',
        value: function toString() {
            var jsonStrs = [];
            var _iteratorNormalCompletion7 = true;
            var _didIteratorError7 = false;
            var _iteratorError7 = undefined;

            try {
                for (var _iterator7 = Object.keys(this)[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
                    var key = _step7.value;

                    if (key == "updateTimestamp") {
                        jsonStrs.push(key + ':"' + this[key] + '"');
                    } else if (!/^\$\S+/g.test(key) && key != 'id' && key != 'isMatched' && key != 'unknown') {
                        var v = this[key];
                        v = angular.toJson(v);
                        if (typeof v == 'string') {
                            v = v.escapeText();
                        }
                        jsonStrs.push(key + ':"' + v + '"');
                    }
                }
            } catch (err) {
                _didIteratorError7 = true;
                _iteratorError7 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion7 && _iterator7.return) {
                        _iterator7.return();
                    }
                } finally {
                    if (_didIteratorError7) {
                        throw _iteratorError7;
                    }
                }
            }

            return ':' + this.$type + '{' + jsonStrs.join(',') + '}';
        }
    }, {
        key: 'toJson',
        value: function toJson() {
            var json = {
                type: this.$type
            };
            var _iteratorNormalCompletion8 = true;
            var _didIteratorError8 = false;
            var _iteratorError8 = undefined;

            try {
                for (var _iterator8 = Object.keys(this)[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
                    var key = _step8.value;

                    if (key == "updateTimestamp") {
                        json[key] = this[key];
                    } else if (!/^\$\S+/g.test(key) && key != 'id' && key != 'isMatched' && key != 'unknown') {
                        json[key] = this[key];
                    }
                }
            } catch (err) {
                _didIteratorError8 = true;
                _iteratorError8 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion8 && _iterator8.return) {
                        _iterator8.return();
                    }
                } finally {
                    if (_didIteratorError8) {
                        throw _iteratorError8;
                    }
                }
            }

            return json;
        }
    }, {
        key: 'getText',
        value: function getText() {
            return this.getTypeName() + ' ' + this.name;
        }
    }, {
        key: 'getTextWithId',
        value: function getTextWithId() {
            return '[' + this.id + '] ' + this.getText();
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            return this.getReadonlyTemplate(edge, g);
        }
    }, {
        key: 'getReadonlyTemplate',
        value: function getReadonlyTemplate(edge, g) {
            return '\n<div class="form-group">\n    <label class="col-sm-2 control-label">' + this.getTypeName() + '</label>\n    <p class="col-sm-10 form-control-static">' + this.name + '</p>\n </div>';
        }
    }, {
        key: 'persist',
        value: function persist() {
            for (var _len3 = arguments.length, callbacks = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
                callbacks[_key3] = arguments[_key3];
            }

            var session = neo4jService.getSession();
            if (this.$state == 'new') {
                var resultPromise = session.run('create (n' + this.toString() + ') return n ');
                resultPromise.then(function (result) {
                    session.close();

                    var _arr = [].concat(callbacks);

                    for (var _i = 0; _i < _arr.length; _i++) {
                        var callback = _arr[_i];
                        callback(result);
                    }
                });
            } else //if(this.$state=='dirty')
                {
                    var sets = '';
                    var _iteratorNormalCompletion9 = true;
                    var _didIteratorError9 = false;
                    var _iteratorError9 = undefined;

                    try {
                        for (var _iterator9 = Object.keys(this)[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
                            var key = _step9.value;

                            if (!/^\$\S+/g.test(key) && key != 'id') {
                                var v = this[key];
                                v = angular.toJson(v);
                                if (typeof v == 'string') {
                                    v = v.escapeText();
                                }
                                sets = sets + ' set n.' + key + '="' + v + '" ';
                            }
                        }
                    } catch (err) {
                        _didIteratorError9 = true;
                        _iteratorError9 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion9 && _iterator9.return) {
                                _iterator9.return();
                            }
                        } finally {
                            if (_didIteratorError9) {
                                throw _iteratorError9;
                            }
                        }
                    }

                    var _resultPromise2 = session.run('start n=node(' + this.id + ') ' + sets + ' RETURN n');
                    _resultPromise2.then(function (result) {
                        session.close();

                        var _arr2 = [].concat(callbacks);

                        for (var _i2 = 0; _i2 < _arr2.length; _i2++) {
                            var callback = _arr2[_i2];
                            callback(result);
                        }
                    });
                }
        }
    }], [{
        key: 'nextHop',
        value: function nextHop(session, current_node_id) {
            return session.run('start n=node(' + current_node_id + ') match (n)-[]->(m) return m').then(function (result) {
                return result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
            });
        }
    }, {
        key: 'previousHop',
        value: function previousHop(session, current_node_id) {
            return session.run('start n=node(' + current_node_id + ') match (m)-[]->(n) return m').then(function (result) {
                return result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
            });
        }
    }, {
        key: 'getAncestors',
        value: function getAncestors(session, current_node_id) {
            return session.run('start n=node(' + current_node_id + ') match (m)-[*]->(n) return m').then(function (result) {
                return result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
            });
        }
    }, {
        key: 'fromNeo4jNode',
        value: function fromNeo4jNode(neo4jNode) {
            //TODO 此处将neo4j返回的节点转换为本地的类型
            var groupType = '';
            var id = neo4jNode["identity"].toString();
            switch (neo4jNode['labels'][0]) {
                case 'Fault':
                    return new FaultNode('raw', { id: id }, neo4jNode['properties']);
                case 'Feature':
                    return new FeatureNode('raw', { id: id }, neo4jNode['properties']);
                case 'Reason':
                    return new ReasonNode('raw', { id: id }, neo4jNode['properties']);
                case 'Component':
                    return new ComponentNode('raw', { id: id }, neo4jNode['properties']);
                case 'MatchFunction':
                    return new MatchFunctionNode('raw', { id: id }, neo4jNode['properties']);
                case 'FeatureGroup':
                    groupType = 'Feature';
                    break;
                case 'ReasonGroup':
                    groupType = 'Reason';
                    break;
                case 'ComponentGroup':
                    groupType = 'Component';
                    break;
                default:
                    return null;
            }
            return new GroupNode(groupType, 'raw', { id: id, combineType: neo4jNode['properties']['combineType'] }, neo4jNode['properties']);
        }
    }, {
        key: 'compare',
        value: function compare(node1, node2) {
            if (node1.$type != node2.$type) {
                return node1.$type > node2.$type ? 1 : -1;
            }
            if (node1.outId != node2.outId) {
                return node1.outId > node2.outId ? 1 : -1;
            }

            if (node1.getText() != node2.getText()) {
                return node1.getText() > node2.getText() ? 1 : -1;
            }

            return node1.id > node2.id ? 1 : -1;
        }
    }]);

    return MyNode;
}();

MyNode.idGenerator = 0;

var ComponentNode = function (_MyNode) {
    _inherits(ComponentNode, _MyNode);

    function ComponentNode() {
        var _ref;

        var $state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'new';

        _classCallCheck(this, ComponentNode);

        for (var _len4 = arguments.length, obj = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
            obj[_key4 - 1] = arguments[_key4];
        }

        return _possibleConstructorReturn(this, (_ref = ComponentNode.__proto__ || Object.getPrototypeOf(ComponentNode)).call.apply(_ref, [this, 'Component', $state, {
            name: "部件名称"
        }].concat(obj)));
    }

    _createClass(ComponentNode, [{
        key: 'getTypeName',
        value: function getTypeName() {
            return "测点位置";
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            // let cps = ComponentNode.components
            //     .filter(nd=>{
            //         for (let eg of $scope.graph.edges){
            //             if(eg.from==edge.from&&eg.to==nd.id)
            //                 return false;
            //         }
            //         return true;
            //     });
            // let index = g.getLinkIndex(edge.id);
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u6D4B\u70B9\u4F4D\u7F6E</label>\n     <div class="col-sm-10">\n    <select class="form-control"\n    data-ng-options="component.name for component in components"\n    data-ng-model="component_ref" \n    data-ng-change="graph.resetLink(' + edge + ',component_ref,reloadGraph)"\n    data-ng-init="component_ref=graph.getNodeFromList(\'' + this.id + '\',components)"\n    ></select>\n </div>\n </div>\n \n <div class="form-group">\n <label class="col-sm-2 control-label">\u64CD\u4F5C</label>\n <p class="col-sm-10 form-control-static">\n <a class="btn" href="javascript:;" ng-click="removeEdge(' + edge + ')">\u5220\u9664\u5F53\u524D\u8282\u70B9</a>\n</p>\n</div>\n';
        }
    }], [{
        key: 'loadComponents',
        value: function loadComponents() {
            var session = neo4jService.getSession();
            var resultPromise = session.run('MATCH (n:Component) RETURN n');
            resultPromise.then(function (result) {
                session.close();
                ComponentNode.components = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
                var _iteratorNormalCompletion10 = true;
                var _didIteratorError10 = false;
                var _iteratorError10 = undefined;

                try {
                    for (var _iterator10 = ComponentNode.loadComponents.callbacks[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
                        var fn = _step10.value;

                        fn(ComponentNode.components);
                    }
                } catch (err) {
                    _didIteratorError10 = true;
                    _iteratorError10 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion10 && _iterator10.return) {
                            _iterator10.return();
                        }
                    } finally {
                        if (_didIteratorError10) {
                            throw _iteratorError10;
                        }
                    }
                }
            });
        }
    }, {
        key: 'loadComponentsFrom',
        value: function loadComponentsFrom(superId) {
            for (var _len5 = arguments.length, callbacks = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
                callbacks[_key5 - 1] = arguments[_key5];
            }

            var session = neo4jService.getSession();
            var resultPromise = session.run('start s=node(' + superId + ') MATCH (s)-[*]->(n:Component) RETURN n');
            resultPromise.then(function (result) {
                session.close();
                var components = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
                var _iteratorNormalCompletion11 = true;
                var _didIteratorError11 = false;
                var _iteratorError11 = undefined;

                try {
                    for (var _iterator11 = callbacks[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
                        var fn = _step11.value;

                        fn(components);
                    }
                } catch (err) {
                    _didIteratorError11 = true;
                    _iteratorError11 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion11 && _iterator11.return) {
                            _iterator11.return();
                        }
                    } finally {
                        if (_didIteratorError11) {
                            throw _iteratorError11;
                        }
                    }
                }
            });
        }
    }]);

    return ComponentNode;
}(MyNode);

ComponentNode.components = [];
// ComponentNode.loadComponents();
ComponentNode.loadComponents.callbacks = [];

var FaultNode = function (_MyNode2) {
    _inherits(FaultNode, _MyNode2);

    function FaultNode() {
        var _ref2;

        var $state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'new';

        _classCallCheck(this, FaultNode);

        for (var _len6 = arguments.length, obj = Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
            obj[_key6 - 1] = arguments[_key6];
        }

        return _possibleConstructorReturn(this, (_ref2 = FaultNode.__proto__ || Object.getPrototypeOf(FaultNode)).call.apply(_ref2, [this, 'Fault', $state, {
            name: "故障名",
            outId: 1,
            suggest: "正常运行"
        }].concat(obj)));
    }

    _createClass(FaultNode, [{
        key: 'fillWithRandomValue',
        value: function fillWithRandomValue() {
            for (var i = 0; i < (this.matrix[0] + 1) * (this.matrix[1] + 1); i++) {
                if (!this.matrix[i + 2]) {
                    this.matrix[i + 2] = Math.random();
                }
            }
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            getCache("fault_module", function (val) {
                FaultNode.modules = val.map(function (x) {
                    if (x.indexOf(':') < 0) {
                        return {
                            category: '',
                            name: x
                        };
                    }
                    var arr = x.split(':', 2);
                    return {
                        category: arr[0],
                        name: arr[1]
                    };
                });
            }, function (callback, cache, name) {
                getConfigure('module', function (data) {
                    cache[name] = {
                        lastTimestamp: new Date().getTime(),
                        value: data
                    };
                    callback(data);
                });
            }, 5000);

            return '\n<div class="form-group">                \n    <label class="col-sm-2 control-label">\u6545\u969C\u5206\u7EC4</label>\n    <div class="col-sm-10">\n    <select class="form-control" \n    data-ng-model="graph.getNode(\'' + this.id + '\').faultCategory" \n    data-ng-options="x for x in [\'\u6C7D\u8F6E\u53D1\u7535\u673A\',\'\u6C34\u8F6E\u53D1\u7535\u673A\',\'\u6C7D\u8F6E\u673A\',\'\u9505\u7089\',\'\u6C34\u8F6E\u673A\',\'\u8F85\u673A\',\'\u6D4B\u8BD5\']"\n    data-ng-init="graph.getNode(\'' + this.id + '\').faultCategory = \'' + this.faultCategory + '\'"\n    ></select>\n    </div>\n</div>\n<div class="form-group">                \n    <label class="col-sm-2 control-label">\u6545\u969C\u6A21\u5757</label>\n    <div class="col-sm-10">\n    <select class="form-control" \n    data-ng-model="graph.getNode(\'' + this.id + '\').faultModule" \n    data-ng-options="x.name as x.name for x in graph.getNode(\'' + this.id + '\').getModules()"\n    data-ng-init="graph.getNode(\'' + this.id + '\').faultModule = \'' + this.faultModule + '\'"\n    ></select>\n    </div>\n</div>\n\n<div class="form-group">\n    <label class="col-sm-2 control-label">\u6545\u969CID</label>\n    <div class="col-sm-10"><input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').outId" placeholder="\u7528\u4E8E\u5BFC\u51FA\u7684ID"></div>\n</div>\n<div class="form-group">\n    <label class="col-sm-2 control-label">\u6545\u969C\u540D\u79F0</label>\n    <div class="col-sm-10">\n\t<input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').name" placeholder="\u8BF7\u8F93\u5165\u540D\u79F0">\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u6545\u969C\u90E8\u4F4D</label>\n    <div class="col-sm-10">\n\t<input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').location" placeholder="\u8BF7\u8F93\u5165\u6545\u969C\u90E8\u4F4D">\n    </div>\n </div>\n  <div class="form-group">\n    <label class="col-sm-2 control-label">\u8FD0\u884C\u5EFA\u8BAE</label>\n    <div class="col-sm-10">\n    <select class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').suggest"\n     data-ng-options="x for x in [\'\u6B63\u5E38\u8FD0\u884C\',\'\u76D1\u89C6\u8FD0\u884C\',\'\u7D27\u6025\u505C\u673A\']"\n     data-ng-init="graph.getNode(\'' + this.id + '\').suggest = \'' + this.suggest + '\'"\n     ></select>\n    </div>\n    <label class="col-sm-2 control-label">\u8FD0\u884C\u63CF\u8FF0</label>\n    <div class="col-sm-10">\n        <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" rows="3" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').suggest_description" placeholder="\u8BF7\u8F93\u5165\u5EFA\u8BAE\u63CF\u8FF0"></textarea>\n    </div>\n     <p class="col-sm-offset-2 col-sm-10 form-control-static help-block">\n     <p>\u8BF4\u660E\uFF1A\u6DFB\u52A0\u5DF2\u5B58\u5728\u8282\u70B9\u4F1A\u81EA\u52A8\u8FDB\u884C\u5B58\u50A8\u64CD\u4F5C\uFF0C\u5E76\u5237\u65B0\u6574\u4E2A\u8F93\u5165\u533A\u5185\u5BB9</p>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachFeature(\'' + this.id + '\')">\u6DFB\u52A0\u7279\u5F81</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u7279\u5F81\u7EC4</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalFeature(\'' + this.id + '\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81\u7EC4</a>\n        <a class="button btn" data-ng-if="allowCause(\'' + this.id + '\')" data-ng-click="attachReason(\'' + this.id + '\')">\u6DFB\u52A0\u539F\u56E0</a>\n        <a class="button btn" data-ng-if="allowCause(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'ReasonGroup\')">\u6DFB\u52A0\u539F\u56E0\u7EC4</a>\n    </p>\n </div>\n';
            // <div class="form-group">
            //         <label class="col-sm-2 control-label">概率表&nbsp;
            // <a class="button btn" data-ng-click="graph.getNode('${this.id}').fillWithRandomValue()">填充随机概率</a>
            //         </label>
            //         <div class="col-sm-10">
            //         <table class="table table-responsive table-bordered" ng-init="fs=graph.getFeatures();rs=graph.getReasons();nf=fs.length;nr=rs.length;graph.getNode('${this.id}').matrix[0] = nf;graph.getNode('${this.id}').matrix[1] = nr;">
            //         <thead>
            //         <tr><td>特征/原因</td><td ng-repeat="reason in rs track by $index">{{reason.getText()}}</td><td>整体</td></tr>
            //     </thead>
            //     <tbody>
            //     <tr ng-repeat="feature in fs track by $index" ng-init="$index2=$index">
            //         <td>{{feature.getText()}}</td><td ng-repeat="reason in rs track by $index">
            //     <input class="form-control" data-ng-model-options="{updateOn:'default blur',debounce:{default:5000,blur:0}}" data-ng-model="graph.getNode('${this.id}').matrix[$index2*(nr+1)+$index+2]">
            //         </td><td> <input class="form-control" data-ng-model-options="{updateOn:'default blur',debounce:{default:5000,blur:0}}" data-ng-model="graph.getNode('${this.id}').matrix[($index2+1)*(nr+1)+1]"></td>
            //     </tr>
            //     </tbody>
            //     <tfoot><tr>
            //     <td>整体</td><td ng-repeat="reason in rs track by $index">
            //     <input class="form-control" data-ng-model-options="{updateOn:'default blur',debounce:{default:5000,blur:0}}" data-ng-model="graph.getNode('${this.id}').matrix[nf*(nr+1)+$index+2]">
            //         </td><td><input class="form-control" data-ng-model-options="{updateOn:'default blur',debounce:{default:5000,blur:0}}" data-ng-model="graph.getNode('${this.id}').matrix[(nf+1)*(nr+1)+1]"></td>
            //     </tr></tfoot>
            //     </table>
            //     </div>
            //     </div>
        }
    }, {
        key: 'getText',
        value: function getText() {
            var sIndex = '';
            if (this.outId != 0) sIndex = '<' + this.outId + '>';
            return '\u6545\u969C' + sIndex + '\uFF1A' + this.name;
        }
    }, {
        key: 'getTypeName',
        value: function getTypeName() {
            return "故障";
        }
    }, {
        key: 'getModules',
        value: function getModules() {
            return FaultNode.modules;
        }
    }], [{
        key: 'loadFaults',
        value: function loadFaults() {
            var session = neo4jService.getSession();
            var resultPromise = session.run('MATCH (n:Fault) RETURN n');
            resultPromise.then(function (result) {
                session.close();
                FaultNode.faults = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
                var _iteratorNormalCompletion12 = true;
                var _didIteratorError12 = false;
                var _iteratorError12 = undefined;

                try {
                    for (var _iterator12 = FaultNode.loadFaults.callbacks[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
                        var fn = _step12.value;

                        fn(FaultNode.faults);
                    }
                } catch (err) {
                    _didIteratorError12 = true;
                    _iteratorError12 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion12 && _iterator12.return) {
                            _iterator12.return();
                        }
                    } finally {
                        if (_didIteratorError12) {
                            throw _iteratorError12;
                        }
                    }
                }
            });
        }
    }]);

    return FaultNode;
}(MyNode);

FaultNode.faults = [];
FaultNode.modules = [];
// FaultNode.loadFaults();
FaultNode.loadFaults.callbacks = [];

var FeatureNode = function (_MyNode3) {
    _inherits(FeatureNode, _MyNode3);

    function FeatureNode() {
        var _ref3;

        var $state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'new';

        _classCallCheck(this, FeatureNode);

        for (var _len7 = arguments.length, obj = Array(_len7 > 1 ? _len7 - 1 : 0), _key7 = 1; _key7 < _len7; _key7++) {
            obj[_key7 - 1] = arguments[_key7];
        }

        var _this9 = _possibleConstructorReturn(this, (_ref3 = FeatureNode.__proto__ || Object.getPrototypeOf(FeatureNode)).call.apply(_ref3, [this, 'Feature', $state, {
            name: "特征名称",
            opertion: "特征函数",
            type: "auto",
            outId: 0,
            params: [],
            $faults: new Set(),
            $reasons: new Set()
        }].concat(obj)));

        _this9.params.forEach(function (param, index) {
            if (param && param.low != null) {
                _this9.params[index] = param.low;
            }
        }, _this9);

        _this9.quantum = _this9.defaultQuantum();
        return _this9;
    }

    _createClass(FeatureNode, [{
        key: 'isAuto',
        value: function isAuto() {
            return this.type == 'auto';
        }
    }, {
        key: 'defaultQuantum',
        value: function defaultQuantum() {
            if (this.quantum instanceof Object) {
                this.quantum = this.quantum.low;
            }
            return this.quantum || 100;
        }
    }, {
        key: 'defaultFrequency',
        value: function defaultFrequency(faultId) {
            var df = {};
            df['' + faultId] = 0;
            return $.extend(true, df, this.frequency);
        }
    }, {
        key: 'totalFrequency',
        value: function totalFrequency() {
            var dfs = this.frequency || {};
            return Object.keys(dfs).map(function (key) {
                return dfs[key];
            }).reduce(function (x, y) {
                return eval(x) + eval(y);
            }, 0);
        }
    }, {
        key: 'getFaults',
        value: function getFaults() {
            return [].concat(_toConsumableArray(this.$faults));
        }
    }, {
        key: 'getReasons',
        value: function getReasons() {
            return [].concat(_toConsumableArray(this.$reasons || []));
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5BFC\u51FAID</label>\n    <div class="col-sm-10">\n        <input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').outId" placeholder="\u7528\u4E8E\u5BFC\u51FA\u7684ID">\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5224\u65AD\u65B9\u5F0F</label>\n    <div class="col-sm-10">\n    <select class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').type" data-ng-options="md.v as md.k for md in [{k:\'\u673A\u5668\u5224\u65AD\',v:\'auto\'},{k:\'\u4EBA\u5DE5\u5224\u65AD\',v:\'manual\'}]"></select>\n    </div>\n </div>\n <div data-ng-show="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u7C7B\u522B</label>\n    <div class="col-sm-10">\n    <input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').name" placeholder="\u8BF7\u8F93\u5165\u540D\u79F0">\n    </div>\n </div>\n <div data-ng-show="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u51FD\u6570</label>\n    <div class="col-sm-10">\n    <input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').opertion" placeholder="\u8BF7\u8F93\u5165\u51FD\u6570\u540D\u79F0">\n    </div>\n </div>\n <div data-ng-show="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u56FA\u5B9A\u53C2\u6570\u5217&nbsp;<a href="#" ng-click="appendArgv(\'' + this.id + '\')">\u8865\u5145\u53C2\u6570</a></label>\n    <ol class="col-sm-10 form-control-static">\n      <li ng-repeat="param in graph.getNode(\'' + this.id + '\').params track by $index">\n        <input class="form-control col-sm-8" ng-model-options="{updateOn: \'blur\'}" ng-model="graph.getNode(\'' + this.id + '\').params[$index]" placeholder="\u53C2\u6570\u503C">\n        <a class="form-control-static col-sm-2" href="#" ng-click="removeArgv(\'' + this.id + '\',$index)">\u5220\u9664\u53C2\u6570</a><br>\n      </li>\n    </ol>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u63CF\u8FF0</label>\n    <div class="col-sm-10">\n    <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" rows="3" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').description" placeholder="\u8BF7\u8F93\u5165\u7279\u5F81\u63CF\u8FF0"></textarea>\n    </div>\n </div>\n <div class="form-group" ng-if="graph.getNode(\'' + this.id + '\').$is_sub_graph">\n    <label class="col-sm-2 control-label">\u7F6E\u4FE1\u5EA6</label>\n    <div class="col-sm-10">\n    <table class="table table-responsive table-bordered">\n    <thead>\n        <tr><td>\u6240\u5C5E\u6545\u969C</td><td>\u9891\u7387</td><td>\u7F6E\u4FE1\u5EA6</td></tr>\n    </thead>\n    <tbody ng-init="graph.getNode(\'' + this.id + '\').quantum = graph.getNode(\'' + this.id + '\').defaultQuantum(); graph.getNode(\'' + this.id + '\').frequency = graph.getNode(\'' + this.id + '\').defaultFrequency(graph.getRoot().id); ">\n        <tr ng-repeat="ft in graph.getNode(\'' + this.id + '\').getFaults()">\n        <td>{{ft.getText()}}</td>\n        <td>{{graph.getNode(\'' + this.id + '\').frequency[ft.id] || 0}}</td>\n        <td>{{((graph.getNode(\'' + this.id + '\').frequency[ft.id] || 0) / graph.getNode(\'' + this.id + '\').defaultQuantum() * 100).toFixed(2)}}%</td>\n        </tr>\n    </tbody>\n    <tfoot>\n        <tr><td>\u603B\u548C</td><td>{{graph.getNode(\'' + this.id + '\').totalFrequency()}}</td>\n        <td>{{(graph.getNode(\'' + this.id + '\').totalFrequency() / graph.getNode(\'' + this.id + '\').defaultQuantum() *100).toFixed(2)}}%</td></tr>\n        <tr><td>\u53EF\u5206\u914D</td><td>{{graph.getNode(\'' + this.id + '\').defaultQuantum() - graph.getNode(\'' + this.id + '\').totalFrequency()}}</td>\n        <td>{{((graph.getNode(\'' + this.id + '\').defaultQuantum() - graph.getNode(\'' + this.id + '\').totalFrequency()) / graph.getNode(\'' + this.id + '\').defaultQuantum() * 100).toFixed(2)}}%</td></tr>\n    </tfoot>\n    </table>\n    \u8BF7\u8F93\u5165\u5BF9\u5F53\u524D\u7684\u6545\u969C\u5206\u914D\u521D\u59CB\u9891\u7387(\u5E94\u5C0F\u4E8E\u7B49\u4E8E\u53EF\u5206\u914D\u7684\u6570\u91CF)\uFF1A\n    <input  ng-change="frequencyUpdated(\'' + this.id + '\')"  ng-model="graph.getNode(\'' + this.id + '\').frequency[graph.getRoot().id]" data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}">\n    </div>\n</div>\n <br>\n <div class="form-group" ng-if="graph.getNode(\'' + this.id + '\').$is_sub_graph2">\n    <label class="col-sm-2 control-label">\u5BF9\u539F\u56E0\u7684\u7F6E\u4FE1\u5EA6</label>\n    <div class="col-sm-10">\n    <table class="table table-responsive table-bordered">\n    <thead>\n        <tr><td>\u6240\u5C5E\u539F\u56E0</td><td>\u7F6E\u4FE1\u5EA6</td></tr>\n    </thead>\n    <tbody>\n        <tr ng-repeat="rid in graph.getNode(\'' + this.id + '\').getReasons(\'' + this.id + '\')">\n        <td>{{graph.getNode(rid).getText()}}</td>\n        <td ng-init="graph.getNode(rid).frequency = graph.getNode(rid).defaultFrequency();">\n        <input  \n          ng-model="graph.getNode(rid).frequency[\'' + this.id + '\']" \n          data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}">\n        </td>\n        </tr>\n    </tbody>\n    </table>\n    </div>\n</div>\n <br>\n <div class="form-group">\n <label class="col-sm-2 control-label">\u64CD\u4F5C</label>\n <p class="col-sm-10 form-control-static">\n     <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachComponent(\'' + this.id + '\')">\u6DFB\u52A0\u6D4B\u70B9\u4F4D\u7F6E</a>\n     <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'ComponentGroup\')">\u6DFB\u52A0\u5143\u4EF6\u7EC4</a>\n     <a class="btn" href="javascript:;" ng-click="removeEdge(' + edge + ')">\u5220\u9664\u5F53\u524D\u8282\u70B9</a>\n </p>\n</div>\n';
        }
    }, {
        key: 'getReadonlyTemplate',
        value: function getReadonlyTemplate(edge, g) {
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5224\u65AD\u65B9\u5F0F</label>\n    <p class="col-sm-10 form-control-static">' + (this.type == 'auto' ? '机器判断' : '人工判断') + '</p>\n </div>\n <div data-ng-show="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u7C7B\u522B</label>\n    <p class="col-sm-10 form-control-static">' + this.name + '</p>\n </div>\n <div data-ng-show="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u51FD\u6570</label>\n    <p class="col-sm-10 form-control-static">' + this.opertion + ' ' + this.params + '</p>\n </div>\n <div data-ng-hide="graph.getNode(\'' + this.id + '\').isAuto()" class="form-group">\n    <label class="col-sm-2 control-label">\u7279\u5F81\u63CF\u8FF0</label>\n    <p class="col-sm-10 form-control-static">' + this.description + '</p>\n </div>';
        }
    }, {
        key: 'getText',
        value: function getText() {
            var sIndex = '';
            if (this.outId != 0) sIndex = '<' + this.outId + '>';
            if (this.isAuto()) return '\u7279\u5F81' + sIndex + '\uFF1A' + this.name + ' ' + this.opertion + ' ' + this.params;else return '\u7279\u5F81' + sIndex + '\uFF1A' + this.description;
        }
    }, {
        key: 'getName',
        value: function getName() {
            if (this.isAuto()) return '' + this.name;else return '' + this.description;
        }
    }, {
        key: 'getExpression',
        value: function getExpression() {
            if (this.isAuto()) return this.name + ' ' + this.opertion + ' ' + this.params;else return '' + this.description;
        }
    }], [{
        key: 'loadFeatures',
        value: function loadFeatures() {
            var session = neo4jService.getSession();
            var resultPromise = session.run('MATCH (a:Feature) RETURN a');
            resultPromise.then(function (result) {
                session.close();
                FeatureNode.features = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });

                FeatureNode.featureTypes = [].concat(_toConsumableArray(new Set(FeatureNode.features.filter(function (feature) {
                    return feature.isAuto();
                }).map(function (feature) {
                    return feature.name;
                }))));

                //TODO Feature 下面的 Component 后续可直接使用loadGraph 中的内容
                FeatureNode.features
                // .filter(feature => feature.isAuto)
                .forEach(function (feature, index) {
                    var session2 = neo4jService.getSession();
                    var resultPromise2 = session2.run('start f=node(' + feature.id + ') MATCH (f)-[*]->(a:Component) RETURN a');
                    resultPromise2.then(function (result) {
                        session2.close();
                        FeatureNode.features[index].components = result.records.map(function (record) {
                            return record.get(0);
                        }).map(function (node) {
                            return node["identity"].toString();
                        });
                    });
                });

                var _iteratorNormalCompletion13 = true;
                var _didIteratorError13 = false;
                var _iteratorError13 = undefined;

                try {
                    for (var _iterator13 = FeatureNode.loadFeatures.callbacks[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
                        var fn = _step13.value;

                        fn(FeatureNode.features, FeatureNode.featureTypes);
                    }
                } catch (err) {
                    _didIteratorError13 = true;
                    _iteratorError13 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion13 && _iterator13.return) {
                            _iterator13.return();
                        }
                    } finally {
                        if (_didIteratorError13) {
                            throw _iteratorError13;
                        }
                    }
                }
            });
        }
    }, {
        key: 'loadFeatures2',
        value: function loadFeatures2(query) {
            for (var _len8 = arguments.length, callbacks = Array(_len8 > 2 ? _len8 - 2 : 0), _key8 = 2; _key8 < _len8; _key8++) {
                callbacks[_key8 - 2] = arguments[_key8];
            }

            var parameters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

            var session = neo4jService.getSession();
            var resultPromise = session.run(query, parameters);
            resultPromise.then(function (result) {
                session.close();
                var features = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });

                var featureTypes = [].concat(_toConsumableArray(new Set(features.filter(function (feature) {
                    return feature.isAuto();
                }).map(function (feature) {
                    return feature.name;
                }))));

                //TODO Feature 下面的 Component 后续可直接使用loadGraph 中的内容
                features
                // .filter(feature => feature.isAuto)
                .forEach(function (feature, index) {
                    var session2 = neo4jService.getSession();
                    var resultPromise2 = session2.run('start f=node(' + feature.id + ') MATCH (f)-[*]->(a:Component) RETURN a');
                    resultPromise2.then(function (result) {
                        session2.close();
                        features[index].components = result.records.map(function (record) {
                            return record.get(0);
                        }).map(function (node) {
                            return node["identity"].toString();
                        });

                        //TODO Callback Here
                        if (index + 1 == features.length) {
                            var _iteratorNormalCompletion14 = true;
                            var _didIteratorError14 = false;
                            var _iteratorError14 = undefined;

                            try {
                                for (var _iterator14 = callbacks[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
                                    var fn = _step14.value;

                                    fn(features, featureTypes);
                                }
                            } catch (err) {
                                _didIteratorError14 = true;
                                _iteratorError14 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion14 && _iterator14.return) {
                                        _iterator14.return();
                                    }
                                } finally {
                                    if (_didIteratorError14) {
                                        throw _iteratorError14;
                                    }
                                }
                            }
                        }
                    });
                });
            });
        }
    }]);

    return FeatureNode;
}(MyNode);

FeatureNode.loadFeatures.callbacks = [];
// FeatureNode.loadFeatures();

var GroupNode = function (_MyNode4) {
    _inherits(GroupNode, _MyNode4);

    function GroupNode(entityType) {
        var _ref4;

        var $state = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'new';

        _classCallCheck(this, GroupNode);

        for (var _len9 = arguments.length, obj = Array(_len9 > 2 ? _len9 - 2 : 0), _key9 = 2; _key9 < _len9; _key9++) {
            obj[_key9 - 2] = arguments[_key9];
        }

        var _this10 = _possibleConstructorReturn(this, (_ref4 = GroupNode.__proto__ || Object.getPrototypeOf(GroupNode)).call.apply(_ref4, [this, entityType + 'Group', $state, {
            combineType: "or",
            outId: 0,
            $faults: new Set(),
            $reasons: new Set()
        }].concat(obj)));

        if (entityType == "Feature") {
            _this10.entityType = entityType;
            _this10.quantum = _this10.defaultQuantum();
        }
        return _this10;
    }

    _createClass(GroupNode, [{
        key: 'getText',
        value: function getText() {
            var sIndex = '';
            if (this.outId != 0) sIndex = '<' + this.outId + '>';
            return GroupNode.getMetaTypeName(this.entityType) + '\u7EC4\u5408' + sIndex + ':' + this.combineType;
        }
    }, {
        key: 'getTypeName',
        value: function getTypeName() {
            return "组合";
        }
    }, {
        key: 'defaultQuantum',
        value: function defaultQuantum() {
            if (this.quantum instanceof Object) {
                this.quantum = this.quantum.low;
            }
            return this.quantum || 100;
        }
    }, {
        key: 'defaultFrequency',
        value: function defaultFrequency(faultId) {
            var df = {};
            df[faultId] = 0;
            return $.extend(true, df, this.frequency);
        }
    }, {
        key: 'totalFrequency',
        value: function totalFrequency() {
            var dfs = this.frequency || {};
            return Object.keys(dfs).map(function (key) {
                return dfs[key];
            }).reduce(function (x, y) {
                return eval(x) + eval(y);
            }, 0);
        }
    }, {
        key: 'getFaults',
        value: function getFaults() {
            return [].concat(_toConsumableArray(this.$faults));
        }
    }, {
        key: 'getReasons',
        value: function getReasons() {
            return [].concat(_toConsumableArray(this.$reasons || []));
        }
    }, {
        key: 'getReadonlyTemplate',
        value: function getReadonlyTemplate(edge, g) {
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u7EC4\u5408\u65B9\u5F0F</label>\n    <p class="col-sm-10 form-control-static">' + this.combineType + '</p>\n </div>';
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            return '\n  <div class="form-group">\n    <label class="col-sm-2 control-label">\u5BFC\u51FAID</label>\n    <div class="col-sm-10">\n    <input type="text" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').outId" placeholder="\u7528\u4E8E\u5BFC\u51FA\u7684ID">\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u7EC4\u5408\u65B9\u5F0F</label>\n    <div class="col-sm-10">\n    <select class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').combineType" data-ng-options="item for item in [\'and\',\'or\',\'not\']" placeholder="\u9009\u62E9\u4E00\u9879"></select>\n    </div>\n </div>\n  <div class="form-group" ng-if="graph.getNode(\'' + this.id + '\').$is_sub_graph">\n    <label class="col-sm-2 control-label">\u7F6E\u4FE1\u5EA6</label>\n    <div class="col-sm-10">\n    <table class="table table-responsive table-bordered">\n    <thead>\n        <tr><td>\u6240\u5C5E\u6545\u969C</td><td>\u9891\u7387</td><td>\u6982\u7387</td></tr>\n    </thead>\n    <tbody ng-init="graph.getNode(\'' + this.id + '\').quantum = graph.getNode(\'' + this.id + '\').defaultQuantum(); graph.getNode(\'' + this.id + '\').frequency = graph.getNode(\'' + this.id + '\').defaultFrequency(graph.getRoot().id); ">\n        <tr ng-repeat="ft in graph.getNode(\'' + this.id + '\').getFaults()">\n        <td>{{ft.getText()}}</td>\n        <td>{{graph.getNode(\'' + this.id + '\').frequency[ft.id] || 0}}</td>\n        <td>{{((graph.getNode(\'' + this.id + '\').frequency[ft.id] || 0) / graph.getNode(\'' + this.id + '\').defaultQuantum() * 100).toFixed(2)}}%</td>\n        </tr>\n    </tbody>\n    <tfoot>\n        <tr><td>\u603B\u548C</td><td>{{graph.getNode(\'' + this.id + '\').totalFrequency()}}</td>\n        <td>{{(graph.getNode(\'' + this.id + '\').totalFrequency() / graph.getNode(\'' + this.id + '\').defaultQuantum() *100).toFixed(2)}}</td></tr>\n        <tr><td>\u53EF\u5206\u914D</td><td>{{graph.getNode(\'' + this.id + '\').defaultQuantum() - graph.getNode(\'' + this.id + '\').totalFrequency()}}</td>\n        <td>{{((graph.getNode(\'' + this.id + '\').defaultQuantum() - graph.getNode(\'' + this.id + '\').totalFrequency()) / graph.getNode(\'' + this.id + '\').defaultQuantum() * 100).toFixed(2)}}</td></tr>\n    </tfoot>\n    </table>\n    \u8BF7\u8F93\u5165\u5BF9\u5F53\u524D\u7684\u6545\u969C\u5206\u914D\u521D\u59CB\u9891\u7387(\u5E94\u5C0F\u4E8E\u7B49\u4E8E\u53EF\u5206\u914D\u7684\u6570\u91CF)\uFF1A\n    <input ng-change="frequencyUpdated(\'' + this.id + '\')" ng-model="graph.getNode(\'' + this.id + '\').frequency[graph.getRoot().id]" data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}">\n    </div>\n  </div>\n    \n  <div class="form-group" ng-if="graph.getNode(\'' + this.id + '\').$is_sub_graph2">\n    <label class="col-sm-2 control-label">\u5BF9\u539F\u56E0\u7684\u7F6E\u4FE1\u5EA6</label>\n    <div class="col-sm-10">\n    <table class="table table-responsive table-bordered">\n    <thead>\n        <tr><td>\u6240\u5C5E\u539F\u56E0</td><td>\u7F6E\u4FE1\u5EA6</td></tr>\n    </thead>\n    <tbody>\n        <tr ng-repeat="rid in graph.getNode(\'' + this.id + '\').getReasons(\'' + this.id + '\')">\n        <td>{{graph.getNode(rid).getText()}}</td>\n        <td ng-init="graph.getNode(rid).frequency = graph.getNode(rid).defaultFrequency();">\n        <input  \n          ng-model="graph.getNode(rid).frequency[\'' + this.id + '\']" \n          data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}">\n        </td>\n        </tr>\n    </tbody>\n    </table>\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5907\u6CE8\u4FE1\u606F</label>\n    <div class="col-sm-10">\n    <textarea rows="3" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').description" placeholder="\u8BF7\u8F93\u5165\u5907\u6CE8\u4FE1\u606F"></textarea>\n    </div>\n    <p class="col-sm-offset-2 col-sm-10 form-control-static help-block">\n        <a class="btn" href="javascript:;" ng-click="removeEdge(' + edge + ')">\u5220\u9664\u5F53\u524D\u8282\u70B9</a></label>\n        <a class="btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachFeature(\'' + this.id + '\')">\u6DFB\u52A0\u7279\u5F81</a>\n        <a class="btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u7279\u5F81\u7EC4</a>\n         <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalFeature(\'' + this.id + '\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81\u7EC4</a>\n        <a class="btn" data-ng-if="allowCause(\'' + this.id + '\')" data-ng-click="attachReason(\'' + this.id + '\')">\u6DFB\u52A0\u539F\u56E0</a>\n        <a class="btn" data-ng-if="allowCause(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'ReasonGroup\')">\u6DFB\u52A0\u539F\u56E0\u7EC4</a>\n        <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachComponent(\'' + this.id + '\')">\u6DFB\u52A0\u5143\u4EF6</a>\n        <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'ComponentGroup\')">\u6DFB\u52A0\u5143\u4EF6\u7EC4</a>\n    </p>\n </div>';
        }
    }], [{
        key: 'getMetaTypeName',
        value: function getMetaTypeName(entityType) {
            switch (entityType) {
                case 'Feature':
                    return "特征";
                case 'Reason':
                    return "原因";
                case 'Component':
                    return "测点";
            }
            return '';
        }
    }]);

    return GroupNode;
}(MyNode);

var MatchFunctionNode = function (_MyNode5) {
    _inherits(MatchFunctionNode, _MyNode5);

    function MatchFunctionNode() {
        var _ref5;

        var $state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'new';

        _classCallCheck(this, MatchFunctionNode);

        for (var _len10 = arguments.length, obj = Array(_len10 > 1 ? _len10 - 1 : 0), _key10 = 1; _key10 < _len10; _key10++) {
            obj[_key10 - 1] = arguments[_key10];
        }

        return _possibleConstructorReturn(this, (_ref5 = MatchFunctionNode.__proto__ || Object.getPrototypeOf(MatchFunctionNode)).call.apply(_ref5, [this, 'MatchFunction', $state, {
            name: "函数名",
            body: '\nfunction (a,params){\n    return false;\n}'
        }].concat(obj)));
    }

    _createClass(MatchFunctionNode, null, [{
        key: 'loadFunctions',
        value: function loadFunctions() {
            var session = neo4jService.getSession();
            var resultPromise = session.run('MATCH (n:MatchFunction) RETURN n');
            resultPromise.then(function (result) {
                session.close();
                MatchFunctionNode.functions = result.records.map(function (record) {
                    return record.get(0);
                }).map(function (node) {
                    return MyNode.fromNeo4jNode(node);
                });
                var _iteratorNormalCompletion15 = true;
                var _didIteratorError15 = false;
                var _iteratorError15 = undefined;

                try {
                    for (var _iterator15 = MatchFunctionNode.loadFunctions.callbacks[Symbol.iterator](), _step15; !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) {
                        var fn = _step15.value;

                        fn(MatchFunctionNode.functions);
                    }
                } catch (err) {
                    _didIteratorError15 = true;
                    _iteratorError15 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion15 && _iterator15.return) {
                            _iterator15.return();
                        }
                    } finally {
                        if (_didIteratorError15) {
                            throw _iteratorError15;
                        }
                    }
                }
            });
        }
    }]);

    return MatchFunctionNode;
}(MyNode);

MatchFunctionNode.functions = [];
// MatchFunctionNode.loadFunctions();
MatchFunctionNode.loadFunctions.callbacks = [];

var matchFactory = function matchFactory(opertion) {
    switch (opertion) {
        case '>':
            return function (a, params) {
                return Number(a) > Number(params[0]);
            };
        case '<':
            return function (a, params) {
                return Number(a) < Number(params[0]);
            };
        case '>=':
            return function (a, params) {
                return Number(a) >= Number(params[0]);
            };
        case '<=':
            return function (a, params) {
                return Number(a) <= Number(params[0]);
            };
        case '=':
            return function (a, params) {
                return a == params[0];
            };
        case 'between':
            return function (a, params) {
                return Number(a) >= Number(params[0]) && Number(a) <= Number(params[1]);
            };
        case 'in':
            return function (a, params) {
                var _iteratorNormalCompletion16 = true;
                var _didIteratorError16 = false;
                var _iteratorError16 = undefined;

                try {
                    for (var _iterator16 = params[Symbol.iterator](), _step16; !(_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done); _iteratorNormalCompletion16 = true) {
                        var param = _step16.value;

                        if (param == a) {
                            return true;
                        }
                    }
                } catch (err) {
                    _didIteratorError16 = true;
                    _iteratorError16 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion16 && _iterator16.return) {
                            _iterator16.return();
                        }
                    } finally {
                        if (_didIteratorError16) {
                            throw _iteratorError16;
                        }
                    }
                }

                return false;
            };
        default:
    }

    var _iteratorNormalCompletion17 = true;
    var _didIteratorError17 = false;
    var _iteratorError17 = undefined;

    try {
        for (var _iterator17 = MatchFunctionNode.functions[Symbol.iterator](), _step17; !(_iteratorNormalCompletion17 = (_step17 = _iterator17.next()).done); _iteratorNormalCompletion17 = true) {
            var func = _step17.value;

            if (func.name == opertion) {
                return eval('(' + func.body + ')');
            }
        }
    } catch (err) {
        _didIteratorError17 = true;
        _iteratorError17 = err;
    } finally {
        try {
            if (!_iteratorNormalCompletion17 && _iterator17.return) {
                _iterator17.return();
            }
        } finally {
            if (_didIteratorError17) {
                throw _iteratorError17;
            }
        }
    }

    return function (a, params) {
        return false;
    };
};

var ReasonNode = function (_MyNode6) {
    _inherits(ReasonNode, _MyNode6);

    function ReasonNode() {
        var _ref6;

        var $state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'new';

        _classCallCheck(this, ReasonNode);

        for (var _len11 = arguments.length, obj = Array(_len11 > 1 ? _len11 - 1 : 0), _key11 = 1; _key11 < _len11; _key11++) {
            obj[_key11 - 1] = arguments[_key11];
        }

        return _possibleConstructorReturn(this, (_ref6 = ReasonNode.__proto__ || Object.getPrototypeOf(ReasonNode)).call.apply(_ref6, [this, 'Reason', $state, {
            name: "原因描述",
            probability: 0.2,
            frequency: {},
            solution: '解决方案',
            outId: 0
        }].concat(obj)));
    }

    _createClass(ReasonNode, [{
        key: 'getText',
        value: function getText() {
            var sIndex = '';
            if (this.outId != 0) sIndex = '<' + this.outId + '>';
            return '\u539F\u56E0' + sIndex + '\uFF1A' + this.name;
        }
    }, {
        key: 'defaultFrequency',
        value: function defaultFrequency(featureId) {
            this.frequency = this.frequency || {};
            if (!this.frequency['' + featureId]) {
                this.frequency['' + featureId] = 0;
            }
            return this.frequency;
        }
    }, {
        key: 'getTemplate',
        value: function getTemplate(edge, g) {
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5BFC\u51FAID</label>\n    <div class="col-sm-10">\n    <input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').outId" placeholder="\u7528\u4E8E\u5BFC\u51FA\u7684ID">\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u539F\u56E0\u63CF\u8FF0</label>\n    <div class="col-sm-10">\n    <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" rows="3" class="form-control" data-ng-model="graph.getNode(\'' + this.id + '\').name" placeholder="\u8BF7\u8F93\u5165\u539F\u56E0\u63CF\u8FF0"></textarea>\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u6982\u7387</label>\n    <div class="col-sm-10">\n    <input data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').probability" placeholder="\u8BF7\u8F93\u5165\u6982\u7387">\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u89E3\u51B3\u65B9\u6848</label>\n    <div class="col-sm-10">\n    <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" rows="3" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').solution" placeholder="\u8BF7\u8F93\u5165\u89E3\u51B3\u65B9\u6848"></textarea>\n    </div>\n </div>\n  <div class="form-group">\n    <label class="col-sm-2 control-label">\u6240\u9700\u5DE5\u5177</label>\n    <div class="col-sm-10">\n    <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" type="text" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').tools" placeholder="\u8BF7\u8F93\u5165\u6240\u9700\u5DE5\u5177"></textarea>\n    </div>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u5907\u54C1\u5907\u4EF6</label>\n    <div class="col-sm-10">\n    <textarea data-ng-model-options="{updateOn:\'default blur\',debounce:{default:5000,blur:0}}" rows="3" class="col-sm-10 form-control" data-ng-model="graph.getNode(\'' + this.id + '\').parts" placeholder="\u8BF7\u8F93\u5165\u5907\u54C1\u5907\u4EF6"></textarea>\n    </div>\n </div>\n  <div class="form-group">\n <label class="col-sm-2 control-label">\u64CD\u4F5C</label>\n <p class="col-sm-10 form-control-static">\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachFeature(\'' + this.id + '\')">\u6DFB\u52A0\u7279\u5F81</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u7279\u5F81\u7EC4</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalFeature(\'' + this.id + '\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81</a>\n        <a class="button btn" data-ng-if="allowFeature(\'' + this.id + '\')" data-ng-click="attachExternalGroup(\'' + this.id + '\',\'FeatureGroup\')">\u6DFB\u52A0\u5DF2\u5B58\u5728\u7279\u5F81\u7EC4</a>\n     <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachComponent(\'' + this.id + '\')">\u6DFB\u52A0\u5143\u4EF6</a>\n     <a class="btn" data-ng-if="allowComponent(\'' + this.id + '\')" data-ng-click="attachGroup(\'' + this.id + '\',\'ComponentGroup\')">\u6DFB\u52A0\u5143\u4EF6\u7EC4</a>\n     &nbsp;<a class="btn" href="javascript:;" ng-click="removeEdge(' + edge + ')">\u5220\u9664\u5F53\u524D\u8282\u70B9</a>\n </p>\n</div>\n';
        }
    }, {
        key: 'getReadonlyTemplate',
        value: function getReadonlyTemplate(edge, g) {
            return '\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u539F\u56E0\u63CF\u8FF0</label>\n    <p class="col-sm-10 form-control-static">' + this.name + '</p>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u6982\u7387</label>\n    <p class="col-sm-10 form-control-static">' + this.probability + '</p>\n </div>\n <div class="form-group">\n    <label class="col-sm-2 control-label">\u89E3\u51B3\u65B9\u6848</label>\n    <p class="col-sm-10 form-control-static">' + this.solution + '</p>\n </div>\n<div class="form-group">\n    <label class="col-sm-2 control-label">\u6240\u9700\u5DE5\u5177</label>\n    <p class="col-sm-10 form-control-static">' + this.tools + '</p>\n </div>\n<div class="form-group">\n    <label class="col-sm-2 control-label">\u5907\u54C1\u5907\u4EF6</label>\n    <p class="col-sm-10 form-control-static">' + this.parts + '</p>\n </div>';
        }
    }]);

    return ReasonNode;
}(MyNode);
